package org.sixtynine.stock.controller;

import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.sixtynine.stock.Constants.CommonData;
import org.sixtynine.stock.ReturnData;
import org.sixtynine.stock.dto.GridPramDTO;
import org.sixtynine.stock.dto.Page;
import org.sixtynine.stock.entity.BaseEntity;
import org.sixtynine.stock.entity.Company;
import org.sixtynine.stock.entity.DailyShareData;
import org.sixtynine.stock.entity.QuarterlyShareData;
import org.sixtynine.stock.entity.User;
import org.sixtynine.stock.model.FileUploadForm;
import org.sixtynine.stock.model.LoadingSearchCriteria;
import org.sixtynine.stock.service.CompanyService;
import org.sixtynine.stock.service.GenericService;
import org.sixtynine.stock.service.QuarterlyShareDataService;
import org.sixtynine.stock.service.content.DataManagerService;
import org.sixtynine.stock.service.file.ExcelProcessorFactory;
import org.sixtynine.stock.service.file.FileDataService;
import org.sixtynine.stock.util.DateUtil;
import org.sixtynine.stock.util.SessionBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author Thilan
 * 
 *         this class use to add , edit and delete Quarterly Share data
 * 
 */

@Controller
@SessionAttributes
public class QuarterlyShareController extends BackEndAuthController {

	/** configure */
	private int RECORDS_PER_PAGE = 10;

	@Autowired
	private GenericService genericService;

	@Autowired
	private FileDataService fileDataService;

	@Autowired
	DataManagerService dataManagerService;

	@Autowired
	QuarterlyShareDataService quarterlyShareDataService;

	@Autowired
	CompanyService companyService;

	@RequestMapping(value = "/admin/quarterlysharedata/search")
	public ModelAndView search(@ModelAttribute LoadingSearchCriteria criteria,
			HttpServletRequest request) {
		ModelAndView modelAndView = null;
		if (!isUserLogged(request)) {
			modelAndView = new ModelAndView("/login/login");
			modelAndView.addObject("registedUser", new User());
			return modelAndView;
		}

		modelAndView = new ModelAndView("/admin/quarterlysharedata/list");
		loadData(1, -1, criteria.getCompanyId(), criteria.getCompanyName(),
				criteria.getFromYear(), criteria.getToYear(),
				criteria.getQuarterCode(), modelAndView, criteria);

		SessionBean sBean = SessionBean.getInstance(request);
		sBean.setAttr(SEARCH_CRITERIA, criteria);

		return modelAndView;
	}

	@RequestMapping(value = "/admin/quarterlysharedata/add")
	public ModelAndView addQuaterData(HttpServletRequest request) {
		ModelAndView modelAndView = null;

		if (!isUserLogged(request)) {
			modelAndView = new ModelAndView("/login/login");
			modelAndView.addObject("registedUser", new User());
			return modelAndView;
		}
		modelAndView = new ModelAndView("/admin/quarterlysharedata/add");
		modelAndView.addObject("quarterlyShareData", new QuarterlyShareData());

		List<BaseEntity> companies = dataManagerService
				.getData(CommonData.COMPANY.toString());
		modelAndView.addObject("companyMap", companies);
		modelAndView.addObject("userLogged", true);

		return modelAndView;
	}

	@RequestMapping(value = "/admin/quarterlysharedata/add/file_process")
	public ModelAndView addingQuarterDataByFile(
			@ModelAttribute("uploadFile") FileUploadForm uploadFile,
			BindingResult result) {

		ModelAndView modelAndView = null;
		StringBuilder message = new StringBuilder();
		if (!result.hasErrors()) {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/list");

			List<BaseEntity> quarterlyShareDataList = genericService
					.findAll(QuarterlyShareData.class);
			modelAndView.addObject("quarterlyShareDataList",
					quarterlyShareDataList);
			MultipartFile multipartFile = uploadFile.getFile();
			ReturnData<String> fileSaveReturnData = fileDataService.saveFile(
					multipartFile,
					ExcelProcessorFactory.FILE_TYPE_QUARTER_SHARE_DATA_LIST,
					null);
			if (fileSaveReturnData._isSuccess()) {
				// if success, process it
				ReturnData<List<? extends BaseEntity>> returnData = fileDataService
						.process(
								multipartFile.getOriginalFilename(),
								ExcelProcessorFactory.FILE_TYPE_QUARTER_SHARE_DATA_LIST);
				if (returnData._isSuccess()) {
					message.append("file "
							+ multipartFile.getOriginalFilename()
							+ " uploaded and inserted successfully");

					modelAndView = new ModelAndView(
							"/admin/quarterlysharedata/list");

					modelAndView.addObject("userLogged", true);
					modelAndView.addObject("message", message);
					modelAndView.addObject("criteria",
							new LoadingSearchCriteria());
					loadData(1, -1, -1, null, -1, -1, null, modelAndView, null);
					// refresh data after insert
					dataManagerService.loadData(CommonData.COMPANY.toString(),
							Company.class);
					modelAndView.addObject("criteria",
							new LoadingSearchCriteria());
				} else {
					message.append(returnData.getMsg());
				}
			} else {
				message.append(fileSaveReturnData.getMsg());
			}
		} else {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/add");
			modelAndView.addObject("quarterlyShareData",
					new QuarterlyShareData());

			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
			modelAndView.addObject("message", message);
		}

		return modelAndView;
	}

	@RequestMapping(value = "admin/quarterlysharedata/add/company_process")
	public ModelAndView addingQuarterByCompany(
			@ModelAttribute FileUploadForm uploadFile, BindingResult result) {

		ModelAndView modelAndView = null;
		StringBuilder message = new StringBuilder();
		if (!result.hasErrors()) {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/list");

			MultipartFile multipartFile = uploadFile.getFile();
			ReturnData<String> fileSaveReturnData = fileDataService
					.saveFile(
							multipartFile,
							ExcelProcessorFactory.FILE_TYPE_COMPANY_QUARTER_SHARE_DATA_LIST,
							null);
			if (fileSaveReturnData._isSuccess()) {
				// if success, process it
				ReturnData<List<? extends BaseEntity>> returnData = fileDataService
						.process(
								multipartFile.getOriginalFilename(),
								ExcelProcessorFactory.FILE_TYPE_COMPANY_QUARTER_SHARE_DATA_LIST);
				if (returnData._isSuccess()) {
					message.append("file "
							+ multipartFile.getOriginalFilename()
							+ " uploaded and inserted successfully");

					List<BaseEntity> quarterlyShareDataList = genericService
							.findAll(QuarterlyShareData.class);
					modelAndView.addObject("quarterlyShareDataList",
							quarterlyShareDataList);
					modelAndView = new ModelAndView(
							"/admin/quarterlysharedata/list");
					modelAndView.addObject("criteria",
							new LoadingSearchCriteria());
					modelAndView.addObject("userLogged", true);
					modelAndView.addObject("message", message);
					loadData(1, -1, -1, null, -1, -1, null, modelAndView, null);
					// refresh data after insert
					dataManagerService.loadData(CommonData.COMPANY.toString(),
							Company.class);
					modelAndView.addObject("criteria",
							new LoadingSearchCriteria());
				} else {
					modelAndView = new ModelAndView(
							"/admin/quarterlysharedata/add");
					modelAndView.addObject("quarterlyShareData",
							new QuarterlyShareData());

					List<BaseEntity> companies = dataManagerService
							.getData(CommonData.COMPANY.toString());
					modelAndView.addObject("companyMap", companies);
					modelAndView.addObject("userLogged", true);
					message.append(returnData.getMsg());
					modelAndView.addObject("message", message);

				}
			} else {
				modelAndView = new ModelAndView("/admin/quarterlysharedata/add");
				modelAndView.addObject("quarterlyShareData",
						new QuarterlyShareData());

				List<BaseEntity> companies = dataManagerService
						.getData(CommonData.COMPANY.toString());
				modelAndView.addObject("companyMap", companies);
				modelAndView.addObject("userLogged", true);

				message.append(fileSaveReturnData.getMsg());
				modelAndView.addObject("message", message);
			}
		} else {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/add");
			modelAndView.addObject("quarterlyShareData",
					new QuarterlyShareData());

			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
			modelAndView.addObject("message", message);
		}

		return modelAndView;
	}

	@RequestMapping(value = "/admin/quarterlysharedata/add/process")
	public ModelAndView addingQuarterData(
			@Valid @ModelAttribute QuarterlyShareData quarterlyShareData,
			BindingResult result) {
		ModelAndView modelAndView = null;
		StringBuilder message = new StringBuilder();
		String quarterCode = quarterlyShareData._getFullQuarterCode();

		if (checkQtrCode(quarterCode) > 4) {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/add");
			modelAndView.addObject("quarterlyShareData",
					new QuarterlyShareData());

			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
			message.append("Quarter code " + quarterCode + " is wrong");
			modelAndView.addObject("message", message);
		}
		if (checkQtrCode(quarterCode) < 1) {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/add");
			modelAndView.addObject("quarterlyShareData",
					new QuarterlyShareData());

			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
			message.append("Quarter code " + quarterCode + " is wrong");
			modelAndView.addObject("message", message);
		}
		if (checkFutureQtr(quarterCode)) {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/add");
			modelAndView.addObject("quarterlyShareData",
					new QuarterlyShareData());

			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
			message.append("Please enter correct year");
			modelAndView.addObject("message", message);
		}

		Criterion criterion = (Restrictions.conjunction().add(
				Restrictions.eq("year", quarterlyShareData.getYear()))
				.add(Restrictions.eq("quarterCode",
						quarterlyShareData.getQuarterCode())));
		List<BaseEntity> dataList = genericService.findByCriteria(criterion,
				QuarterlyShareData.class);
		if (dataList.size() > 0) {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/add");
			modelAndView.addObject("quarterlyShareData",
					new QuarterlyShareData());

			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
			modelAndView.addObject("message", message);
		}

		if (!result.hasErrors()) {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/list");
			List<BaseEntity> quarterlyShareDataList = genericService
					.findAll(QuarterlyShareData.class);
			modelAndView.addObject("quarterlyShareDataList",
					quarterlyShareDataList);
			modelAndView.addObject("criteria", new LoadingSearchCriteria());
			modelAndView.addObject("userLogged", true);
			genericService.saveOrUpdate(quarterlyShareData);
			modelAndView.addObject("message", message);
			// refresh data after insert
			dataManagerService.loadData(CommonData.COMPANY.toString(),
					Company.class);
			loadData(1, -1, quarterlyShareData.getCompany().getId(),
					quarterlyShareData.getCompany().getName(), -1, -1,
					quarterlyShareData.getQuarterCode(), modelAndView, null);
		} else {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/add");
			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
		}

		return modelAndView;

	}

	@RequestMapping(value = "/admin/quarterlysharedata/list")
	public ModelAndView listOfQuarterData(
			HttpServletRequest request,
			@RequestParam(value = "page", required = false) Integer page,
			@RequestParam(value = "totalRecords", required = false) Integer totalRecords) {
		ModelAndView modelAndView = null;

		if (!isUserLogged(request)) {
			modelAndView = new ModelAndView("/login/login");
			modelAndView.addObject("registedUser", new User());
			return modelAndView;
		}
		modelAndView = new ModelAndView("/admin/quarterlysharedata/list");
		loadData(page, totalRecords, -1, null, -1, -1, null, modelAndView, null);
		modelAndView.addObject("criteria", new LoadingSearchCriteria());
		modelAndView.addObject("userLogged", true);

		return modelAndView;
	}

	/**
	 * load data
	 * 
	 * @param page
	 * @param totalRecords
	 * @param companyId
	 * @param fromDate
	 * @param toDate
	 * @param modelAndView
	 */
	private void loadData(Integer page, Integer totalRecords, int companyId,
			String companyName, int fromYear, int toYear, String quarterCode,
			ModelAndView modelAndView, LoadingSearchCriteria criteria) {
		GridPramDTO gridPramDTO = new GridPramDTO();
		gridPramDTO.setRows(RECORDS_PER_PAGE);
		if (page != null) {
			gridPramDTO.setPage(page);
		} else {
			gridPramDTO.setPage(1);
		}
		if (totalRecords != null) {
			gridPramDTO._setTotalNumberOfRecords(totalRecords);
		}

		if (companyId == 0) {
			companyId = -1;
		}
		if (companyName == "") {
			companyName = null;
		}
		Page<QuarterlyShareData> quarterlyShareDataPage = quarterlyShareDataService
				.searchQuarterlyShareData(companyId, companyName, fromYear,
						toYear, quarterCode, "year", "company", gridPramDTO);
		modelAndView
				.addObject("quarterlyShareDataPage", quarterlyShareDataPage);

		List<BaseEntity> compaies = dataManagerService
				.getData(CommonData.COMPANY.toString());

		modelAndView.addObject("companyMap", compaies);
		if (criteria == null) {
			criteria = new LoadingSearchCriteria();
			criteria.setCompanyId(companyId);
			criteria.setFromYear(fromYear);
			criteria.setToYear(toYear);
			criteria.setQuarterCode(quarterCode);
		}
		modelAndView.addObject("criteria", criteria);

	}

	@RequestMapping(value = "/admin/quarterlysharedata/edit/{id}", method = RequestMethod.GET)
	public ModelAndView editQuarterlyShareData(@PathVariable Integer id,
			HttpServletRequest request) {
		ModelAndView modelAndView = null;
		if (!isUserLogged(request)) {
			modelAndView = new ModelAndView("/login/login");
			modelAndView.addObject("registedUser", new User());

			return modelAndView;
		}

		modelAndView = new ModelAndView("/admin/quarterlysharedata/edit");
		BaseEntity quarterlyShareData = genericService.findById(id,
				QuarterlyShareData.class);
		modelAndView.addObject("quarterlyShareData", quarterlyShareData);
		List<BaseEntity> companies = genericService.findAll(Company.class);
		modelAndView.addObject("companyMap", companies);

		return modelAndView;
	}

	@RequestMapping(value = "/admin/quarterlysharedata/edit/{id}", method = RequestMethod.POST)
	public ModelAndView edditingQuarterlyShareData(
			@Valid @ModelAttribute("quarterlyShareData") QuarterlyShareData quarterlyShareData,
			BindingResult result, @PathVariable Integer id) {

		ModelAndView modelAndView = null;
		if (!result.hasErrors()) {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/list");
			modelAndView.addObject("userLogged", true);
			loadData(1, -1, quarterlyShareData.getCompany().getId(),
					quarterlyShareData.getCompany().getName(), -1, -1,
					quarterlyShareData.getQuarterCode(), modelAndView, null);
			genericService.saveOrUpdate(quarterlyShareData);
			return modelAndView;
		} else {
			modelAndView = new ModelAndView("/admin/quarterlysharedata/edit");
			List<BaseEntity> companies = genericService.findAll(Company.class);
			modelAndView.addObject("companyMap", companies);
			String message = "Please enter correct data.";
			modelAndView.addObject("message", message);
		}
		return modelAndView;

	}

	@RequestMapping(value = "/admin/quarterlysharedata/delete/{id}", method = RequestMethod.GET)
	public ModelAndView deleteQuarterlyShareData(@PathVariable Integer id) {
		ModelAndView modelAndView = new ModelAndView(
				"/admin/quarterlysharedata/list");
		genericService.delete(id, QuarterlyShareData.class);

		modelAndView.addObject("userLogged", true);
		String message = "Recode was successfully deleted.";
		modelAndView.addObject("message", message);
		modelAndView.addObject("criteria", new LoadingSearchCriteria());
		loadData(1, -1, -1, null, -1, -1, null, modelAndView, null);
		return modelAndView;
	}

	public int checkQtrCode(String code) {
		String qtrCode = code.split("_")[1];
		String qtr = qtrCode.substring(1);

		return Integer.parseInt(qtr);
	}

	public boolean checkFutureQtr(String code) {

		int year = Integer.parseInt(code.split("_")[0]);
		int currentYear = DateUtil.getYearFromDate(new Date());

		return currentYear < year;
	}

	@RequestMapping(value = "/admin/quarterlysharedata/delete/selected")
	public ModelAndView deleteSelectedDailyShareData(
			HttpServletRequest request,
			@RequestParam(value = "deleteIds", required = false) Integer[] deleteIds) {
		ModelAndView modelAndView = null;

		if (deleteIds != null) {
			for (Integer deleteId : deleteIds) {
				genericService.delete(deleteId, DailyShareData.class);
			}
		}

		modelAndView = new ModelAndView("/admin/quarterlysharedata/list");
		modelAndView.addObject("criteria", new LoadingSearchCriteria());
		String message = "Record successfully deleted.";
		modelAndView.addObject("message", message);
		loadData(1, -1, -1, null, -1, -1, null, modelAndView, null);

		return modelAndView;
	}

	@RequestMapping(value = "/admin/quarterlysharedata/deleteFiltered")
	public ModelAndView deleteFilteredQuarterShareData(
			HttpServletRequest request) {
		ModelAndView modelAndView = new ModelAndView(
				"/admin/quarterlysharedata/list");

		SessionBean sBean = SessionBean.getInstance(request);
		LoadingSearchCriteria criteria = (LoadingSearchCriteria) sBean
				.getAttr(SEARCH_CRITERIA);
		if (criteria == null) {
			criteria = new LoadingSearchCriteria();
		}

		if (criteria.getCompanyId() == 0) {
			criteria.setCompanyId(-1);
		}

		if (criteria.getCompanyName() != null) {

			Company company = companyService.findCompany(
					criteria.getCompanyName(), criteria.getCompanyId());

			if (company != null) {
				criteria.setCompanyId(company.getId());
			} else {
				criteria.setCompanyId(-1);
			}
		}
		// delete the selected criteria
		quarterlyShareDataService.deleteQuarterlyShareData(
				criteria.getCompanyId(), criteria.getFromYear(),
				criteria.getToYear(), criteria.getQuarterCode());

		// reload the page
		loadData(1, -1, criteria.getCompanyId(), criteria.getCompanyName(),
				criteria.getFromYear(), criteria.getToYear(),
				criteria.getQuarterCode(), modelAndView, criteria);

		return modelAndView;
	}

}
